<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="简介、接口、类、函数、泛型、枚举">
<meta property="og:type" content="article">
<meta property="og:title" content="TypeScript 入门">
<meta property="og:url" content="https://chuangges.gitee.io/2019/11/03/11-1-typescript%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="简介、接口、类、函数、泛型、枚举">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2019-11-03T06:04:28.000Z">
<meta property="article:modified_time" content="2023-09-25T06:17:04.100Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="JS 扩展">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://chuangges.gitee.io/2019/11/03/11-1-typescript%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>TypeScript 入门 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2019/11/03/11-1-typescript%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          TypeScript 入门
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-11-03 14:04:28" itemprop="dateCreated datePublished" datetime="2019-11-03T14:04:28+08:00">2019-11-03</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-09-25 14:17:04" itemprop="dateModified" datetime="2023-09-25T14:17:04+08:00">2023-09-25</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JS-%E6%89%A9%E5%B1%95/" itemprop="url" rel="index"><span itemprop="name">JS 扩展</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>23k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>20 分钟</span>
            </span>
            <div class="post-description">简介、接口、类、函数、泛型、枚举</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、简介"><a href="#一、简介" class="headerlink" title="一、简介"></a>一、简介</h1><blockquote>
<p>基于 JS 新增了强类型、静态类型、语法检查、代码编译等特性的微软推出语言，注意 TS 并不可以直接运行而是需要通过编译器转换为 JS 代码才可以在 NodeJS 或浏览器环境下执行。<code>语言类型</code>：<strong>动态类型</strong> (运行期间检查类型，变量在首次赋值时自动记录类型而不需要指定)、<strong>静态类型</strong> (编译期间检查类型，变量在使用前需要先声明类型)、<strong>强类型</strong> (没有强制转换就不变)、<strong>弱类型</strong> (类型可以显式或隐式地改变)。<code>优势</code>：强类型特性可以避免编辑代码时的低级错误、按需输出 JS 版本而不需要兼容脚本、代码标准化而不用考虑不同 JS 版本、主流框架和 JS 新特性的支持。TS 基础学习后可挑战题库 <code>type-challenges</code>。</p>
</blockquote>
<h2 id="开发准备"><a href="#开发准备" class="headerlink" title="开发准备"></a>开发准备</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 安装编译</span></span><br><span class="line">npm i typescript -g    <span class="comment">// tsc 编译器</span></span><br><span class="line">tsc ./test.<span class="property">ts</span> -w       <span class="comment">// -w 实时编译</span></span><br><span class="line">tsc --noEmit           <span class="comment">// 检查代码但不生成文件</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// .vscode/launch.json：调试环境</span></span><br><span class="line"><span class="string">&quot;configurations&quot;</span>: [</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="string">&quot;type&quot;</span>: <span class="string">&quot;node&quot;</span>,</span><br><span class="line">    <span class="string">&quot;request&quot;</span>: <span class="string">&quot;launch&quot;</span>,</span><br><span class="line">    <span class="string">&quot;name&quot;</span>: <span class="string">&quot;Typescript&quot;</span>,</span><br><span class="line">    <span class="string">&quot;program&quot;</span>: <span class="string">&quot;$&#123;workspaceFolder&#125;/src/index.ts&quot;</span>,</span><br><span class="line">    <span class="string">&quot;preLaunchTask&quot;</span>: <span class="string">&quot;tsc: build - tsconfig.json&quot;</span>,</span><br><span class="line">    <span class="string">&quot;sourceMaps&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;skipFiles&quot;</span>: [<span class="string">&quot;&lt;node_internals&gt;/**&quot;</span>],</span><br><span class="line">    <span class="string">&quot;outFiles&quot;</span>: [<span class="string">&quot;$&#123;workspaceFolder&#125;/**/*.js&quot;</span>]</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// tsconfig.json：tsc --init 生成的编译配置文件</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;compilerOptions&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;target&quot;</span>: <span class="string">&quot;es6&quot;</span>,            <span class="comment">// 生成版本（es3、es5、es2015、ES2016)</span></span><br><span class="line">    <span class="string">&quot;module&quot;</span>: <span class="string">&quot;commonjs&quot;</span>,       <span class="comment">// 加载器 (commonjs、AMD、es2015)</span></span><br><span class="line">    <span class="string">&quot;removeComments&quot;</span>: <span class="literal">false</span>,    <span class="comment">// 编译时删除注释</span></span><br><span class="line">    <span class="string">&quot;noImplicitAny&quot;</span>: <span class="literal">false</span>,     <span class="comment">// 无法判断类型时报错，true 则用 any</span></span><br><span class="line">    <span class="string">&quot;esModuleInterop&quot;</span>: <span class="literal">true</span>,    <span class="comment">// 允许 export 导出</span></span><br><span class="line">    <span class="string">&quot;isolatedModules&quot;</span>: <span class="literal">true</span>,    <span class="comment">// 将每个⽂件做为单独模块</span></span><br><span class="line">    <span class="string">&quot;importHelpers&quot;</span>: <span class="literal">true</span>,      <span class="comment">// 引入 tslib helper 函数</span></span><br><span class="line">    <span class="string">&quot;sourceMap&quot;</span>: <span class="literal">true</span>,          <span class="comment">// 生成 sourceMap</span></span><br><span class="line">    <span class="string">&quot;outDir&quot;</span>: <span class="string">&quot;./dist&quot;</span>,         <span class="comment">// 指定生成目录</span></span><br><span class="line">    <span class="string">&quot;allowJs&quot;</span>: <span class="literal">true</span>,            <span class="comment">// 允许编译 js</span></span><br><span class="line">    <span class="string">&quot;noEmit&quot;</span>: <span class="literal">false</span>             <span class="comment">// 是否不输出文件</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">&quot;exclude&quot;</span>: [<span class="string">&quot;node_modules&quot;</span>],  <span class="comment">// 不编译的目录</span></span><br><span class="line">  <span class="string">&quot;include&quot;</span>: [<span class="string">&quot;./src/**/*.ts&quot;</span>]  <span class="comment">// 编译文件：* 文件匹配、** 忽略深度</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">==================== 打包工具中的 <span class="title class_">TypeScript</span> ====================</span><br><span class="line"><span class="comment">// 1、rollup.config.js：Rollup + TypeScript</span></span><br><span class="line"><span class="keyword">import</span> typescript <span class="keyword">from</span> <span class="string">&#x27;@rollup/plugin-typescript&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="attr">input</span>: <span class="string">&#x27;src/index.ts&#x27;</span>,</span><br><span class="line">    <span class="attr">output</span>: &#123;</span><br><span class="line">        <span class="attr">dir</span>: <span class="string">&#x27;output&#x27;</span>,</span><br><span class="line">        <span class="attr">format</span>: <span class="string">&#x27;cjs&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">plugins</span>: [<span class="title function_">typescript</span>()]</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、webpack.config.js：Webpack + TypeScript</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">    <span class="attr">entry</span>: <span class="string">&#x27;./src/index.ts&#x27;</span>,</span><br><span class="line">    <span class="attr">module</span>: &#123;</span><br><span class="line">        <span class="attr">rules</span>: [&#123; </span><br><span class="line">            <span class="attr">test</span>: <span class="regexp">/\.tsx?$/</span>, </span><br><span class="line">            <span class="attr">use</span>: <span class="string">&#x27;ts-loader&#x27;</span>, </span><br><span class="line">            <span class="attr">exclude</span>: <span class="regexp">/node_modules/</span> </span><br><span class="line">        &#125;],</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">resolve</span>: &#123;</span><br><span class="line">        <span class="attr">extensions</span>: [<span class="string">&#x27;.tsx&#x27;</span>, <span class="string">&#x27;.ts&#x27;</span>, <span class="string">&#x27;.js&#x27;</span>],</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">output</span>: &#123;</span><br><span class="line">        <span class="attr">filename</span>: <span class="string">&#x27;bundle.js&#x27;</span>,</span><br><span class="line">        <span class="attr">path</span>: path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;dist&#x27;</span>),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、.babelrc：Babel + TypeScript</span></span><br><span class="line">&#123; <span class="string">&quot;presets&quot;</span>: [<span class="string">&quot;@babel/preset-typescript&quot;</span>] &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4、esbuild.config.js：Vite + ESbuild + TypeScript</span></span><br><span class="line"><span class="keyword">import</span> esbuild <span class="keyword">from</span> <span class="string">&#x27;esbuild&#x27;</span>      <span class="comment">// 打包工具 Go 语言编写</span></span><br><span class="line"><span class="keyword">import</span> swc <span class="keyword">from</span> <span class="string">&#x27;@swc/core&#x27;</span>        <span class="comment">// 编译器类似 babel</span></span><br><span class="line"><span class="keyword">import</span> fs <span class="keyword">from</span> <span class="string">&#x27;node:fs&#x27;</span></span><br><span class="line"><span class="keyword">await</span> esbuild.<span class="title function_">build</span>(&#123;</span><br><span class="line">    <span class="attr">entryPoints</span>: [<span class="string">&#x27;./index.ts&#x27;</span>],   <span class="comment">// 入口文件</span></span><br><span class="line">    <span class="attr">outdir</span>: <span class="string">&quot;dist&quot;</span>,                <span class="comment">// 导出目录</span></span><br><span class="line">    <span class="attr">bundle</span>: <span class="literal">true</span>,                  <span class="comment">// 单独打包</span></span><br><span class="line">    <span class="attr">treeShaking</span>: <span class="literal">true</span>,             <span class="comment">// 摇树优化</span></span><br><span class="line">    <span class="attr">loader</span>: &#123;<span class="string">&#x27;.js&#x27;</span>: <span class="string">&#x27;js&#x27;</span>, <span class="string">&#x27;.ts&#x27;</span>: <span class="string">&#x27;ts&#x27;</span>, <span class="string">&#x27;.jsx&#x27;</span>: <span class="string">&#x27;jsx&#x27;</span>, <span class="string">&#x27;.tsx&#x27;</span>: <span class="string">&#x27;tsx&#x27;</span>&#125;,</span><br><span class="line">    <span class="attr">define</span>: &#123; <span class="string">&#x27;process.env.NODE_ENV&#x27;</span>: <span class="string">&#x27;&quot;production&quot;&#x27;</span> &#125;,</span><br><span class="line">    <span class="attr">plugins</span>: [&#123;</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&quot;swc-loader&quot;</span>,</span><br><span class="line">        <span class="title function_">setup</span>(<span class="params">build</span>) &#123;</span><br><span class="line">            build.<span class="title function_">onLoad</span>(&#123; <span class="attr">filter</span>: <span class="regexp">/\.(js|ts|tsx|jsx)$/</span> &#125;, <span class="function">(<span class="params">args</span>) =&gt;</span> &#123;</span><br><span class="line">                <span class="keyword">const</span> content = fs.<span class="title function_">readFileSync</span>(args.<span class="property">path</span>, <span class="string">&quot;utf-8&quot;</span>)</span><br><span class="line">                <span class="keyword">const</span> &#123; code &#125; = swc.<span class="title function_">transformSync</span>(content, &#123;</span><br><span class="line">                    <span class="attr">filename</span>: args.<span class="property">path</span></span><br><span class="line">                &#125;)</span><br><span class="line">                <span class="keyword">return</span> &#123; <span class="attr">contents</span>: code &#125;</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;],</span><br><span class="line">    </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>


<h2 id="基础类型"><a href="#基础类型" class="headerlink" title="基础类型"></a>基础类型</h2><ul>
<li>JS 类型：Boolean、Number、String、Object、null、undefined、Symbol。</li>
<li>新增类型：Tuple (元组)、Enum (枚举)、Void (空值)、Any (任意值)、Never (永不存在的值)、unknown (类型不确定的值)。类型关系可通过 X extends Y 判断前者是否子类型。</li>
</ul>
  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">num</span>: <span class="built_in">number</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">str</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">isDone</span>: <span class="built_in">boolean</span> = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">num = <span class="string">&#x27;123&#x27;</span>;     <span class="comment">// 报错</span></span><br><span class="line">str = <span class="number">123</span>;       <span class="comment">// 报错</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Array：各元素的类型必须相同</span></span><br><span class="line"><span class="keyword">var</span> <span class="attr">arr</span>:<span class="built_in">boolean</span>[] = [<span class="literal">true</span>, <span class="literal">false</span>];  <span class="comment">// 元素类型后面添加 []</span></span><br><span class="line"><span class="keyword">var</span> <span class="attr">arr</span>:<span class="title class_">Array</span>&lt;<span class="built_in">number</span>&gt; = [<span class="number">6</span>, <span class="number">2</span>, <span class="number">3</span>];  <span class="comment">// 数组泛型：Array&lt;类型&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Tuple：一个有不同数据类型的数组，参数和类型一一对应 (不能缺少)</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">x</span>:[<span class="built_in">string</span>, <span class="built_in">number</span>];</span><br><span class="line">x = [<span class="string">&#x27;hello&#x27;</span>, <span class="number">10</span>];  <span class="comment">// OK</span></span><br><span class="line">x = [<span class="number">10</span>, <span class="string">&#x27;hello&#x27;</span>];  <span class="comment">// Error</span></span><br><span class="line">x[<span class="number">3</span>] = <span class="string">&#x27;world&#x27;</span>;     <span class="comment">// OK，访问越界元素时使用联合类型(str、num)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Enum：枚举值为数字或字符串，赋值后后面的值递增</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Status</span> &#123;success = <span class="number">1</span>, error = <span class="number">2</span>, cancel, wait&#125;;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">flag</span>:<span class="title class_">Status</span> = <span class="title class_">Status</span>.<span class="property">success</span>;  <span class="comment">// 枚举值 1</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Status</span>[<span class="number">2</span>]);            <span class="comment">// 变量名 cancel</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Any：相当于关闭类型检查，尽量不用</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">notSure</span>:<span class="built_in">any</span> = <span class="number">4</span>;</span><br><span class="line">notSure = <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">list</span>:<span class="built_in">any</span>[] = [<span class="number">1</span>, <span class="literal">true</span>, <span class="string">&quot;free&quot;</span>];</span><br><span class="line">list[<span class="number">1</span>] = <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// undefined：void 的一个子集</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Void：只能用于返回空值的函数</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">warnUser</span>(<span class="params"></span>):<span class="built_in">void</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;This is my warning message&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Props</span> = &#123;</span><br><span class="line">    <span class="attr">getValue</span>: <span class="function">() =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// null、undefined：默认是所有类型的子类型，可以赋值给任意类型</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">u</span>: <span class="built_in">number</span> = <span class="literal">undefined</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">n</span>: <span class="literal">null</span> = <span class="literal">null</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Never：用于永远不会执行或结束的函数，是所有类型的子类型</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">error</span>(<span class="params">message: <span class="built_in">string</span></span>): <span class="built_in">never</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(message);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;never&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params"></span>): <span class="built_in">never</span> &#123; </span><br><span class="line">    <span class="keyword">let</span> count = <span class="number">1</span>; </span><br><span class="line">    <span class="keyword">while</span>(count) &#123; count++; &#125;</span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="comment">// Object：表示非原始类型</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">obj</span>:<span class="built_in">object</span> = &#123; <span class="attr">name</span>: <span class="string">&#x27;Wang&#x27;</span> &#125;;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">obj</span>:&#123; <span class="attr">name</span>: <span class="built_in">string</span>, age?: <span class="built_in">number</span> &#125; = &#123; </span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;Wang&quot;</span>, </span><br><span class="line">    <span class="attr">age</span>: <span class="number">25</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Object</span> &#123;</span><br><span class="line">    <span class="title function_">new</span>(value?: <span class="built_in">any</span>): <span class="title class_">Object</span>;</span><br><span class="line">    <span class="title function_">create</span>(<span class="attr">o</span>: <span class="built_in">object</span> | <span class="literal">null</span>): <span class="built_in">any</span>;</span><br><span class="line">    <span class="attr">constructor</span>: <span class="title class_">Function</span>;</span><br><span class="line">    <span class="title function_">toString</span>(): <span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">hasOwnProperty</span>(<span class="attr">v</span>: <span class="title class_">PropertyKey</span>): <span class="built_in">boolean</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">create</span>(<span class="literal">undefined</span>);  <span class="comment">// 报错</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// unknown：可以任意值赋值，但不可调用</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">foo</span>: <span class="built_in">unknown</span> = <span class="string">&#x27;string&#x27;</span>;</span><br><span class="line">foo.<span class="title function_">substr</span>(<span class="number">1</span>);                    <span class="comment">// Error：静态检查报错</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">test</span>(<span class="params">input: <span class="built_in">unknown</span></span>): <span class="built_in">number</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="title class_">Array</span>.<span class="title function_">isArray</span>(input)) &#123;</span><br><span class="line">        <span class="keyword">return</span> input.<span class="property">length</span>;      <span class="comment">// Pass：已识别为 array</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> input.<span class="property">length</span>;          <span class="comment">// Error: unknown 类型</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="类型变量"><a href="#类型变量" class="headerlink" title="类型变量"></a>类型变量</h2><blockquote>
<p>enum 仅用来定义枚举类型、interface 可以用来定义函数和对象以及类、type 可以大多数基础类型。但是这三种定义方式都相当于 const 而定义后不可改变。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line">type A = string;</span><br><span class="line">type B = number[];</span><br><span class="line">type C = <span class="function">(<span class="params">num: number</span>) =&gt;</span> number;</span><br><span class="line">type D = &#123; <span class="attr">age</span>: number; <span class="attr">name</span>: string  &#125;;</span><br><span class="line">type G = [<span class="number">1</span>, number, <span class="number">2</span>, string];</span><br><span class="line"><span class="keyword">const</span> <span class="attr">g</span>: G = [<span class="number">1</span>, <span class="number">111</span>, <span class="number">2</span>, <span class="string">&quot;hello&quot;</span>];</span><br><span class="line"></span><br><span class="line">type X = readonly [<span class="number">1</span>, number];</span><br><span class="line">type Y = [...X];  <span class="comment">// 解构后可改</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 变量属性</span></span><br><span class="line">type b1 = <span class="title class_">Names</span>[<span class="number">0</span>];         <span class="comment">// string</span></span><br><span class="line">type b2 = <span class="title class_">Names</span>[<span class="string">&#x27;length&#x27;</span>];  <span class="comment">// 报错</span></span><br><span class="line"></span><br><span class="line">type <span class="title class_">Lang</span> = [<span class="string">&#x27;js&#x27;</span>, <span class="string">&#x27;java&#x27;</span>, <span class="string">&#x27;python&#x27;</span>, <span class="string">&#x27;rust&#x27;</span>];</span><br><span class="line">type <span class="title class_">Len</span> = <span class="title class_">Lang</span>[<span class="string">&#x27;length&#x27;</span>];  <span class="comment">// 正常</span></span><br><span class="line"></span><br><span class="line">type <span class="title class_">Str</span> = <span class="string">&#x27;hello&#x27;</span>;</span><br><span class="line">type s = <span class="title class_">Str</span>[<span class="number">0</span>];            <span class="comment">// string，注意不是 h</span></span><br><span class="line">type sLen = <span class="title class_">Str</span>[<span class="string">&#x27;length&#x27;</span>]   <span class="comment">// number 而非具体数字</span></span><br><span class="line"></span><br><span class="line">type F = <span class="function">() =&gt;</span> <span class="keyword">void</span>;</span><br><span class="line">type f1 = keyof F;          <span class="comment">// never;</span></span><br><span class="line">type f2 = keyof &#123;&#125;;         <span class="comment">// never;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 类型的父子关系：子类型的值可赋值给父类型，但反之报错。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 具体值是基础类型的子类型：比如 1 是 number 的子类型。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 联合类型中的部分是整体的子类型：1 是 1 | 2 的子类型。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> never 是所有类型的子类型、对象判断子类型逐个属性比较。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> undefined 根据 tsconfig strictNullChecks 取值。</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line">type <span class="title class_">Son</span> = <span class="number">1</span></span><br><span class="line">type <span class="title class_">Parent</span> = <span class="number">2</span> | string</span><br><span class="line"><span class="keyword">let</span> <span class="attr">s</span>: <span class="title class_">Son</span> = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">p</span>: <span class="title class_">Parent</span> = <span class="number">2</span>;</span><br><span class="line">s = p  <span class="comment">// 报错</span></span><br><span class="line">p = s  <span class="comment">// 正常</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params"></span>): never &#123; <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>() &#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">a</span>: <span class="number">1</span> = <span class="title function_">foo</span>();   <span class="comment">// 可赋值说明 never 是 1 的子类型。</span></span><br><span class="line"></span><br><span class="line">type <span class="title class_">Button</span> = &#123; <span class="attr">size</span>: <span class="string">&#x27;mini&#x27;</span> | <span class="string">&#x27;large&#x27;</span> &#125;</span><br><span class="line">type <span class="title class_">MyButton</span> = &#123; <span class="attr">size</span>: <span class="string">&#x27;mini&#x27;</span>, <span class="attr">color</span>: <span class="string">&#x27;red&#x27;</span> | <span class="string">&#x27;blue&#x27;</span>&#125;</span><br><span class="line">type <span class="title class_">IsSonButton</span> = <span class="title class_">MyButton</span> <span class="keyword">extends</span> <span class="title class_">Button</span> ? <span class="literal">true</span> : <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="attr">a</span>: <span class="literal">undefined</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">b</span>: number = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">c</span>: <span class="keyword">void</span> | any;</span><br><span class="line">c = a; <span class="comment">// 正常：undefined 是 void、any 的子类型，无关 tsconfig。</span></span><br><span class="line">b = a; <span class="comment">// strictNullChecks: true =&gt; 报错：不是其它类型的子类型。</span></span><br><span class="line">b = a; <span class="comment">// strictNullChecks: false ==&gt; 正常：是其它类型的子类型。</span></span><br><span class="line"></span><br><span class="line">type A = never | string;  <span class="comment">// 父子的联合类型等于父类类型 string。</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">interface <span class="title class_">Person</span> &#123; <span class="attr">name</span>: string; <span class="attr">age</span>: number; &#125;</span><br><span class="line">interface <span class="title class_">Sum</span> &#123; (<span class="attr">num1</span>: number, <span class="attr">num2</span>: number): number; &#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">getSum</span>: <span class="title class_">Sum</span> = <span class="function">(<span class="params">a: number, b: number</span>) =&gt;</span> a + b</span><br><span class="line">type <span class="title class_">Name</span> = <span class="title class_">Person</span>[<span class="string">&#x27;name&#x27;</span>];     <span class="comment">// string</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">enum <span class="title class_">Color</span> &#123; <span class="variable constant_">GREEN</span>, <span class="variable constant_">RED</span>, <span class="variable constant_">BLUE</span> &#125;</span><br><span class="line">type <span class="title class_">Red</span> = <span class="title class_">Color</span>.<span class="property">Red</span>;    <span class="comment">// 0</span></span><br></pre></td></tr></table></figure>


<h2 id="操作符"><a href="#操作符" class="headerlink" title="操作符"></a>操作符</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// keyof：获取类型的所有键值，可用于限制访问对象的 key，因为 any 不可做索引。</span></span><br><span class="line">type <span class="title class_">Person</span> = &#123; <span class="attr">name</span>: string; <span class="attr">age</span>: number; &#125;</span><br><span class="line">type <span class="title class_">Key</span> = keyof <span class="title class_">Person</span>;      <span class="comment">// &#x27;name&#x27; | &#x27;age&#x27;</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getValue</span> (<span class="attr">p</span>: <span class="title class_">Person</span>, <span class="attr">k</span>: keyof <span class="title class_">Person</span>) &#123; <span class="keyword">return</span> p[k]; &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// typeof：获取一个对象/实例的类型</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">me</span>: <span class="title class_">Person</span> = &#123; <span class="attr">name</span>: <span class="string">&#x27;a&#x27;</span>, <span class="attr">age</span>: <span class="number">16</span> &#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">you</span>: <span class="keyword">typeof</span> me = &#123; <span class="attr">name</span>: <span class="string">&#x27;b&#x27;</span>, <span class="attr">age</span>: <span class="number">69</span> &#125;</span><br><span class="line">type <span class="title class_">PersonKey</span> = keyof <span class="keyword">typeof</span> me;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// in：只能用于类型定义中遍历枚举类型</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">obj</span>: <span class="title class_">TypeToNumber</span>&lt;<span class="title class_">Person</span>&gt; = &#123; <span class="attr">name</span>: <span class="number">10</span>, <span class="attr">age</span>: <span class="number">10</span> &#125;</span><br><span class="line">type <span class="title class_">TypeToNumber</span>&lt;T&gt; = &#123; [key <span class="keyword">in</span> keyof T]: number &#125;</span><br></pre></td></tr></table></figure>

<h2 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ! 非空判断：可用在变量名或函数名之后。</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">onClick</span>(<span class="params">callback?: () =&gt; <span class="keyword">void</span></span>) &#123;</span><br><span class="line">    callback!();  <span class="comment">// 参数是可选入参，加 ! 之后则 TS 编译不报错</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Demo</span>(<span class="params"></span>): <span class="variable constant_">JSX</span>.<span class="property">Elememt</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> divRef = useRef&lt;<span class="title class_">HTMLDivElement</span>&gt;();</span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 组件 Mount 后才触发 useEffect，current 一定有值</span></span><br><span class="line">      divRef.<span class="property">current</span>!.<span class="title function_">scrollIntoView</span>();  </span><br><span class="line">    &#125;, []);</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">ref</span>=<span class="string">&#123;divRef&#125;</span>&gt;</span>Demo<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ? 可选：undefined 在非严格模式下会被重新赋值，void 0 会返回 undefined</span></span><br><span class="line">obj?.<span class="property">prop</span>  obj?.[index]  func?.(args)</span><br><span class="line">a?.<span class="property">b</span> 编译为 a === <span class="literal">null</span> || a === <span class="keyword">void</span> <span class="number">0</span> ? <span class="keyword">void</span> <span class="number">0</span> : a.<span class="property">b</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ?? 空值合并：只对 null/undefined 生效，|| 对 false/&#x27;&#x27;/NaN/0 等空值也生效</span></span><br><span class="line"><span class="keyword">let</span> b = a ?? <span class="number">10</span>    编译为</span><br><span class="line"><span class="keyword">let</span> b = a !== <span class="literal">null</span> &amp;&amp; a !== <span class="keyword">void</span> <span class="number">0</span> ? a : <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// _ 数字分隔符：为了便于数字的阅读，编译后的代码是没有下划线的</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">num</span>:number = <span class="number">1_2_345.6_78_9</span></span><br></pre></td></tr></table></figure>


<h1 id="二、接口"><a href="#二、接口" class="headerlink" title="二、接口"></a>二、接口</h1><blockquote>
<p>接口是一个对外的规范和约定，用于为属性、函数等类型命名和第三方代码定义契约。</p>
</blockquote>
<h2 id="属性类型"><a href="#属性类型" class="headerlink" title="属性类型"></a>属性类型</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 约束对象属性</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 1、确定属性：完全匹配</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 2、可选属性：？表示可选</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 3、任意属性：任意类型</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 4、只读属性：readonly</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line">    age?: <span class="built_in">number</span>;</span><br><span class="line">    [<span class="attr">propName</span>: <span class="built_in">string</span>]: <span class="built_in">any</span>;</span><br><span class="line">    <span class="keyword">readonly</span> <span class="attr">x</span>: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">p1</span>: <span class="title class_">Point</span> = &#123; <span class="attr">name</span>: <span class="string">&#x27;Tom&#x27;</span>, <span class="attr">age</span>: <span class="number">25</span>, <span class="attr">x</span>: <span class="number">10</span> &#125;;</span><br></pre></td></tr></table></figure>


<h2 id="函数类型"><a href="#函数类型" class="headerlink" title="函数类型"></a>函数类型</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 约束函数的传入参数和返回值：都是字符串</span></span><br><span class="line"><span class="keyword">interface</span> encrypt &#123;</span><br><span class="line">    (<span class="attr">key</span>:<span class="built_in">string</span>, <span class="attr">value</span>:<span class="built_in">string</span>):<span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">md5</span>:encrypt = <span class="keyword">function</span>(<span class="params">key:<span class="built_in">string</span>, value:<span class="built_in">string</span></span>):<span class="built_in">string</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> key + value;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="可索引类型"><a href="#可索引类型" class="headerlink" title="可索引类型"></a>可索引类型</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 对数组和对象的约束：可通过索引访问的类型</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">UserList</span> &#123;</span><br><span class="line">    <span class="keyword">readonly</span> [<span class="attr">index</span>: <span class="built_in">number</span>]: <span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">arr</span>:<span class="title class_">UserList</span> = [<span class="number">1</span>, <span class="string">&#x27;Tom&#x27;</span>]; <span class="comment">// 报错</span></span><br><span class="line">arr[<span class="number">1</span>] = <span class="string">&quot;Mark&quot;</span>;               <span class="comment">// 报错</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">UserObj</span> &#123;</span><br><span class="line">    [<span class="attr">index</span>:<span class="built_in">string</span>]: <span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">obj</span>:<span class="title class_">UserObj</span> = &#123;<span class="attr">age</span>: <span class="number">20</span>&#125;;  <span class="comment">// 报错</span></span><br></pre></td></tr></table></figure>


<h2 id="类类型"><a href="#类类型" class="headerlink" title="类类型"></a>类类型</h2><blockquote>
<p>多个类的共有特性可提取为一个用来约束属性和方法的接口，但它只是一个规范和约定而只是检验类的结构，没有类的访问修饰符和具体方法，不能像类一样被实例化。</p>
</blockquote>
  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 接口实现：只约束类的公共属性和方法、只约束类的实例部分</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">ClockInterface</span> &#123;</span><br><span class="line">    <span class="attr">currentTime</span>: <span class="title class_">Date</span>;</span><br><span class="line">    <span class="keyword">new</span> (<span class="attr">hour</span>: <span class="built_in">number</span>, <span class="attr">minute</span>: <span class="built_in">number</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Clock</span> <span class="keyword">implements</span> <span class="title class_">ClockInterface</span> &#123;</span><br><span class="line">    <span class="comment">// currentTime: Date                 // 报错</span></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">h: <span class="built_in">number</span>, n: <span class="built_in">number</span></span>) &#123;  <span class="comment">// 报错</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">setTime</span>(<span class="params">d: <span class="built_in">Date</span></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">curTime</span> = d;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 接口继承：实现接口的分割和重用。</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Animal</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="attr">eat</span>: <span class="function">() =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Felidae</span> &#123;</span><br><span class="line">    <span class="attr">claw</span>: <span class="built_in">number</span>;</span><br><span class="line">    <span class="attr">run</span>: <span class="function">() =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Cat</span> <span class="keyword">implements</span> <span class="title class_">Animal</span>, <span class="title class_">Felidae</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="attr">claw</span>: <span class="built_in">number</span>;</span><br><span class="line">    <span class="title function_">eat</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;tag&#x27;</span>, <span class="string">&#x27;I love eat Food!&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="attr">run</span>: () &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;tag&#x27;</span>, <span class="string">&#x27;My speed is fast!&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">cat</span>: <span class="title class_">Cat</span> = <span class="keyword">new</span> <span class="title class_">Cat</span>();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 混合类型：Counter 接口服务 getCounter 方法、counter 对象</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Counter</span> &#123;</span><br><span class="line">    (<span class="attr">start</span>: <span class="built_in">number</span>): <span class="built_in">string</span>;</span><br><span class="line">    <span class="attr">interval</span>: <span class="built_in">number</span>;</span><br><span class="line">    <span class="title function_">reset</span>(): <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getCounter</span>(<span class="params"></span>): <span class="title class_">Counter</span> &#123;</span><br><span class="line">    <span class="keyword">let</span> counter = &lt;<span class="title class_">Counter</span>&gt;<span class="keyword">function</span> (<span class="params">start: <span class="built_in">number</span></span>) &#123; &#125;;</span><br><span class="line">    counter.<span class="property">interval</span> = <span class="number">123</span>;</span><br><span class="line">    counter.<span class="property">reset</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123; &#125;;</span><br><span class="line">    <span class="keyword">return</span> counter;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> c = <span class="title function_">getCounter</span>();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 接口继承类：继承类的成员但是不去实现，Button </span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Control</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="attr">state</span>: <span class="built_in">any</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">SelectableControl</span> <span class="keyword">extends</span> <span class="title class_">Control</span> &#123;</span><br><span class="line">    <span class="title function_">select</span>(): <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Image</span> <span class="keyword">implements</span> <span class="title class_">SelectableControl</span> &#123;</span><br><span class="line">    <span class="title function_">select</span>(<span class="params"></span>) &#123; &#125;    <span class="comment">// 报错：缺少 state 属性</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="三、类"><a href="#三、类" class="headerlink" title="三、类"></a>三、类</h1><ul>
<li><strong>类 Class</strong>：由静态部分和实例部分组成，抽象描述了一种事物的属性和方法，比如猫类。</li>
<li><strong>对象 Object</strong>：通过 new 实例化而继承了类所有属性和方法的实例对象，比如加菲猫。</li>
<li><strong>封装 Encapsulation</strong>：隐藏内部操作细节并只暴露对外接口，保证了数据不被外部更改。</li>
<li><strong>继承 Inheritance</strong>：子类(派生类) 通过 extends 继承 父类(基类) 除了私有成员和构造函数之外的所有特性。注意 TS 不支持一次继承多个类，但支持多重继承（A 继承 B，B 继承 C）。</li>
<li><strong>多态 Polymorphism</strong>：由继承而产生的不同子类，它们对同一个方法可以有不同的响应。</li>
<li><strong>修饰符 Modifiers</strong>：一些用于限定成员性质的关键字。</li>
<li><strong>存取器 getter、setter</strong>：用于改变属性的读取和赋值行为。</li>
<li><strong>抽象类 Abstract Class</strong>：提供其他类继承的的基类（父类）。不允许被实例化。抽象方法只能包含在抽象类中并且必须在子类中实现，非抽象方法可以直接使用而无需重复实现。</li>
<li><strong>接口 Interfaces</strong>：不同类之间公有的属性或方法可以抽象成一个接口。接口可以被类实现（implements）。一个类只能继承自另一个类，但是可以实现多个接口。</li>
</ul>
<h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 不使用 constructor</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span>&#123;</span><br><span class="line">    <span class="attr">name</span>:<span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Student</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Person</span>&#123;</span><br><span class="line">    <span class="title function_">getInfo</span>(<span class="params">age:<span class="built_in">number</span>=<span class="number">20</span></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">name</span> + <span class="string">&quot;: &quot;</span> + age;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用 constructor + super</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span>&#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name:<span class="built_in">string</span></span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getInfo</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">name</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Student</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Person</span>&#123;</span><br><span class="line">    <span class="attr">age</span>: <span class="built_in">number</span>;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name:<span class="built_in">string</span>, age:<span class="built_in">number</span></span>)&#123;</span><br><span class="line">        <span class="variable language_">super</span>(name);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">age</span> = age;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getInfo</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">let</span> superMsg = <span class="variable language_">super</span>.<span class="title function_">getInfo</span>();</span><br><span class="line">        <span class="keyword">return</span> superMsg + <span class="string">&quot;:&quot;</span> + <span class="variable language_">this</span>.<span class="property">age</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">&quot;李四&quot;</span>, <span class="number">20</span>);</span><br></pre></td></tr></table></figure>


<h2 id="多继承"><a href="#多继承" class="headerlink" title="多继承"></a>多继承</h2><blockquote>
<p>TS 中不允许一个子类继承多个父类，只能通过 mixins 模拟实现。mixins 混入用于将一个对象的方法和属性直接拷贝到另一个对象，是面向对象继承的一种替代方案。</p>
</blockquote>
  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">sayHello</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`Helo <span class="subst">$&#123; <span class="variable language_">this</span>.name &#125;</span>!`</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="attr">grade</span>: <span class="built_in">number</span>;</span><br><span class="line">    <span class="title function_">study</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;I need Study!&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 将两个父类的属性和方法做占位，但只定义而不去实现</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SmartObject</span> <span class="keyword">implements</span> <span class="title class_">Person</span>, <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span> = <span class="string">&#x27;person&#x27;</span>;</span><br><span class="line">    <span class="attr">sayHello</span>: <span class="function">() =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line">    <span class="attr">grade</span>: <span class="built_in">number</span> = <span class="number">3</span>;</span><br><span class="line">    <span class="attr">study</span>: <span class="function">() =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 混入实现：直接将需要继承的所有属性都拷贝过去</span></span><br><span class="line"><span class="title function_">applyMixins</span>(<span class="title class_">SmartObject</span>, [<span class="title class_">Person</span>, <span class="title class_">Student</span>]);</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">applyMixins</span>(<span class="params">derivedCtor: <span class="built_in">any</span>, baseCtors: <span class="built_in">any</span>[]</span>) &#123;</span><br><span class="line">    baseCtors.<span class="title function_">forEach</span>(<span class="function"><span class="params">baseCtor</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="title class_">Object</span>.<span class="title function_">getOwnPropertyNames</span>(baseCtor.<span class="property"><span class="keyword">prototype</span></span>).<span class="title function_">forEach</span>(<span class="function"><span class="params">name</span> =&gt;</span> &#123;</span><br><span class="line">            derivedCtor.<span class="property"><span class="keyword">prototype</span></span>[name] = baseCtor.<span class="property"><span class="keyword">prototype</span></span>[name];</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="修饰符"><a href="#修饰符" class="headerlink" title="修饰符"></a>修饰符</h2><pre><code><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span>&#123;</span><br><span class="line">    <span class="attr">age</span>:<span class="built_in">number</span>;      <span class="comment">// 公有(默认)，在当前类内部、子类、类外部都可以访问。</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="attr">sex</span>:<span class="built_in">string</span>;   <span class="comment">// 受保护，只能在当前类内部及其子类可以访问。</span></span><br><span class="line">    <span class="keyword">private</span> <span class="attr">name</span>:<span class="built_in">string</span>;    <span class="comment">// 私有，只能在当前类的内部访问。</span></span><br><span class="line">    <span class="keyword">readonly</span> <span class="attr">x</span>:<span class="built_in">number</span>;      <span class="comment">// 声明时或构造函数中声明只读属性。</span></span><br><span class="line">    <span class="keyword">static</span> <span class="attr">y</span>: <span class="title class_">String</span>;       <span class="comment">// 静态属性和方法存在于类本身而非实例上。</span></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name:<span class="built_in">string</span>, age:<span class="built_in">number</span>, sex:<span class="built_in">string</span></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">run</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">`我是<span class="subst">$&#123;<span class="variable language_">this</span>.name&#125;</span>`</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">static</span> <span class="title function_">printInfo</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Person</span>.<span class="property">y</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Student</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Person</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name:<span class="built_in">string</span>, age:<span class="built_in">number</span>, sex:<span class="built_in">string</span></span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(name, age, sex)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">run1</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">name</span>);   <span class="comment">// 报错</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Person</span>.<span class="title function_">printInfo</span>()   <span class="comment">// 直接调用静态方法</span></span><br><span class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="string">&quot;张三丰&quot;</span>, <span class="number">23</span>, <span class="string">&quot;男&quot;</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(p.<span class="property">name</span>, p.<span class="property">sex</span>);    <span class="comment">// 报错</span></span><br></pre></td></tr></table></figure>
</code></pre>
<h2 id="存取器"><a href="#存取器" class="headerlink" title="存取器"></a>存取器</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 自定义存取数据之前的业务逻辑</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="attr">age</span>: <span class="built_in">number</span>;</span><br><span class="line">    <span class="keyword">get</span> <span class="title function_">age</span>() &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_age</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">set</span> <span class="title function_">age</span>(<span class="params">inputAge: <span class="built_in">number</span>=<span class="number">20</span></span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (inputAge &gt; <span class="number">0</span> &amp;&amp; inputAge &lt;&gt; <span class="number">100</span>) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">_age</span> = inputAge;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> p = <span class="keyword">new</span> <span class="title class_">Person</span>()</span><br><span class="line">p.<span class="property">age</span> = <span class="number">200</span></span><br></pre></td></tr></table></figure>


<h2 id="抽象类"><a href="#抽象类" class="headerlink" title="抽象类"></a>抽象类</h2><blockquote>
<p>和接口一样都无法实例化，区别如下：抽象类多用于实现业务上的严谨性而接口则定义各种规范，抽象类只能作为父类被继承而接口可作为子类继承、抽象类中非抽象方法可以包含具体实现但接口中不能、抽象类中的抽象方法在子类中必须实现。</p>
</blockquote>
  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 抽象类：可以使用修饰符、部分实现方法。</span></span><br><span class="line"><span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Animal</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="attr">name</span>:<span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name:<span class="built_in">string</span></span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 抽象方法：不包含具体实现，要求子类中必须实现此方法</span></span><br><span class="line">    <span class="keyword">abstract</span> <span class="title function_">eat</span>():<span class="built_in">any</span>;</span><br><span class="line">    <span class="comment">// 非抽象方法：无需要求子类实现或重写</span></span><br><span class="line">    <span class="title function_">run</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;非抽象方法，不要子类实现、重写&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Dog</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Animal</span>&#123;</span><br><span class="line">    <span class="title function_">eat</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">name</span>;  <span class="comment">// 子类必须实现抽象方法</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> dog = <span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;tom&quot;</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(dog.<span class="title function_">eat</span>());</span><br></pre></td></tr></table></figure>


<h2 id="高级技巧"><a href="#高级技巧" class="headerlink" title="高级技巧"></a>高级技巧</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 构造函数：通过 typeof 获取构造函数而非实例的类型，包含静态和构造函数。</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Greeter</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> greeting = <span class="string">&#x27;Hello, there&#x27;</span></span><br><span class="line">    <span class="title function_">greet</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Greeter</span>.<span class="property">greeting</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">greeterMaker</span>: <span class="keyword">typeof</span> <span class="title class_">Greeter</span> = <span class="title class_">Greeter</span></span><br><span class="line">greeterMaker.<span class="property">greeting</span> = <span class="string">&#x27;Hey there&#x27;</span></span><br><span class="line"><span class="keyword">let</span> g = <span class="keyword">new</span> <span class="title function_">greeterMaker</span>()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 将类当做接口使用：类定义时会创建实例类型和一个构造函数。</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Point</span> &#123; <span class="attr">x</span>: <span class="built_in">number</span> <span class="attr">y</span>: <span class="built_in">number</span> &#125;</span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Point3</span>d <span class="keyword">extends</span> <span class="title class_">Point</span> &#123; <span class="attr">z</span>: <span class="built_in">number</span> &#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">p</span>: <span class="title class_">Point3</span>d = &#123;<span class="attr">x</span>: <span class="number">1</span>, <span class="attr">y</span>: <span class="number">2</span>, <span class="attr">z</span>: <span class="number">3</span>&#125;</span><br></pre></td></tr></table></figure>


<h1 id="四、函数"><a href="#四、函数" class="headerlink" title="四、函数"></a>四、函数</h1><h2 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h2><blockquote>
<p>函数的类型由传入参数和返回值组成，它们都需要指定数据类型。参数类型只要匹配即可而不会验证参数名是否正确，没有返回值时必须指定类型为 void 而不能留空。</p>
</blockquote>
  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数声明</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">sum</span>(<span class="params">x: <span class="built_in">number</span>, y: <span class="built_in">number</span></span>): <span class="built_in">number</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x + y;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数表达式</span></span><br><span class="line"><span class="keyword">let</span> sum = <span class="keyword">function</span>(<span class="params">x: <span class="built_in">number</span></span>): <span class="built_in">number</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> x + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 完整函数类型: =&gt; 表示函数的定义，左右两侧分别是输入和输出类型。</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">sum</span>: <span class="function">(<span class="params">a: <span class="built_in">number</span></span>) =&gt;</span> <span class="built_in">number</span> = <span class="keyword">function</span>(<span class="params">x: <span class="built_in">number</span></span>): <span class="built_in">number</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> x + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过接口定义</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Search</span> &#123;</span><br><span class="line">    (<span class="attr">source</span>: <span class="built_in">string</span>, <span class="attr">name</span>: <span class="built_in">string</span>): <span class="built_in">boolean</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">s</span>: <span class="title class_">Search</span> = <span class="keyword">function</span>(<span class="params">source: <span class="built_in">string</span>, name: <span class="built_in">string</span></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> source.<span class="title function_">search</span>(name) !== -<span class="number">1</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 没有参数没有返回值</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">run1</span>(<span class="params"></span>):<span class="built_in">void</span>&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 没有参数有返回值</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">run2</span>(<span class="params"></span>):<span class="built_in">string</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;2&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 有参有返回值</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">run3</span>(<span class="params">name:<span class="built_in">string</span>, age:<span class="built_in">number</span></span>):<span class="built_in">string</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;name&#125;</span>: <span class="subst">$&#123;age&#125;</span>`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 有参没有返回值</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">run4</span>(<span class="params">name:<span class="built_in">string</span>,</span>):<span class="built_in">void</span>&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(name)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数永远不会返回</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">bar</span>(<span class="params"></span>): <span class="built_in">never</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;never reach&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 可选参数：必须放在最后面</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">firstName: <span class="built_in">string</span>, lastName?: <span class="built_in">string</span></span>)&#123;</span><br><span class="line">    <span class="keyword">if</span> (lastName) &#123;</span><br><span class="line">        <span class="keyword">return</span> firstName + lastName;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> firstName;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 默认参数：不用放到最后</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">name: <span class="built_in">string</span>, age:<span class="built_in">number</span>=<span class="number">20</span></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;name&#125;</span>: <span class="subst">$&#123;age&#125;</span>`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 剩余参数：ES6 规定 rest 参数只能是最后一个参数</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">sum2</span>(<span class="params">...list: <span class="built_in">number</span>[]</span>): <span class="built_in">number</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">var</span> i =<span class="number">0</span>;i&lt;list.<span class="property">length</span>;i++)&#123;</span><br><span class="line">        sum += list[i]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> sum;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="重载"><a href="#重载" class="headerlink" title="重载"></a>重载</h2><blockquote>
<p>支持一个函数接受不同数量或类型的参数并作出不同处理。TS 优先从最前面的函数定义开始匹配，所以多个函数定义如果有包含关系就需要在前面写下精确定义 (输入数字则输出数字)。</p>
</blockquote>
  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 反转数字或字符串</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">reverse</span>(<span class="params">x: <span class="built_in">number</span></span>): <span class="built_in">number</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">reverse</span>(<span class="params">x: <span class="built_in">string</span></span>): <span class="built_in">string</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">reverse</span>(<span class="params">x: <span class="built_in">number</span> | <span class="built_in">string</span></span>): <span class="built_in">number</span> | <span class="built_in">string</span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> x === <span class="string">&#x27;number&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Number</span>(x.<span class="title function_">toString</span>().<span class="title function_">split</span>(<span class="string">&#x27;&#x27;</span>).<span class="title function_">reverse</span>().<span class="title function_">join</span>(<span class="string">&#x27;&#x27;</span>));</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> x === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> x.<span class="title function_">split</span>(<span class="string">&#x27;&#x27;</span>).<span class="title function_">reverse</span>().<span class="title function_">join</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line">    <span class="title function_">add</span>(<span class="attr">a</span>: <span class="built_in">number</span>, <span class="attr">b</span>: <span class="built_in">number</span>): <span class="built_in">number</span>;</span><br><span class="line">    <span class="title function_">add</span>(<span class="attr">a</span>: <span class="built_in">number</span>, <span class="attr">b</span>: <span class="built_in">string</span>): <span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">add</span>(<span class="attr">a</span>: <span class="built_in">string</span>, <span class="attr">b</span>: <span class="built_in">string</span>): <span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">add</span>(<span class="attr">a</span>: <span class="built_in">string</span>, <span class="attr">b</span>: <span class="built_in">number</span>): <span class="built_in">string</span>;</span><br><span class="line">    <span class="title function_">add</span>(<span class="params">a: Combinable, b: Combinable</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> a === <span class="string">&#x27;string&#x27;</span> || <span class="keyword">typeof</span> b === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> a.<span class="title function_">toString</span>() + b.<span class="title function_">toString</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> a + b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> calculator = <span class="keyword">new</span> <span class="title class_">Calculator</span>();</span><br><span class="line"><span class="keyword">const</span> result = calculator.<span class="title function_">add</span>(<span class="string">&#x27;Semlinker&#x27;</span>, <span class="string">&#x27; Kakuqo&#x27;</span>);</span><br></pre></td></tr></table></figure>


<h1 id="五、泛型"><a href="#五、泛型" class="headerlink" title="五、泛型"></a>五、泛型</h1><blockquote>
<p>一种动态调用时才指定具体类型的宽泛类型，常用于创建对象或调用方法时将类型看作参数。</p>
</blockquote>
<h2 id="基础使用"><a href="#基础使用" class="headerlink" title="基础使用"></a>基础使用</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// JS 函数返回传入的值，TS 泛型指定传入的类型</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params">arg</span>) &#123; <span class="keyword">return</span> arg; &#125;</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Foo</span>&lt;T&gt; = T;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 普通类型：T 任意类型、K 对象的键类型、V 对象的值类型、E 元素类型。</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Dog</span>&lt;T&gt; = &#123; <span class="attr">name</span>: <span class="built_in">string</span>, <span class="attr">type</span>: T &#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Cat</span>&lt;T&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="attr">type</span>: T;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"><span class="keyword">type</span>: T</span>) &#123; <span class="variable language_">this</span>.<span class="property">type</span> = <span class="keyword">type</span>; &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">dog</span>: <span class="title class_">Dog</span>&lt;<span class="built_in">number</span>&gt; = &#123; <span class="attr">name</span>: <span class="string">&#x27;ww&#x27;</span>, <span class="attr">type</span>: <span class="number">20</span> &#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">cat</span>: <span class="title class_">Cat</span>&lt;<span class="built_in">number</span>&gt; = <span class="keyword">new</span> <span class="title class_">Cat</span>&lt;<span class="built_in">number</span>&gt;(<span class="number">20</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MinClass</span>&lt;T&gt; &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="attr">list</span>:T[] = [];</span><br><span class="line">    <span class="title function_">add</span>(<span class="attr">num</span>:T): <span class="built_in">void</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">list</span>.<span class="title function_">push</span>(num);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="title class_">MinClass</span>&lt;<span class="built_in">number</span>&gt;();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数</span></span><br><span class="line"><span class="keyword">function</span> swipe&lt;T, U&gt;(<span class="attr">value</span>: [T, U]): [U, T] &#123;</span><br><span class="line">  <span class="keyword">return</span> [value[<span class="number">1</span>], value[<span class="number">0</span>]];</span><br><span class="line">&#125;</span><br><span class="line">swipe&lt;<span class="title class_">Cat</span>&lt;<span class="built_in">number</span>&gt;, <span class="title class_">Dog</span>&lt;<span class="built_in">number</span>&gt;&gt;([cat, dog])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 接口定义一</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">ConfigFn</span> &#123; &lt;T&gt;(<span class="attr">value</span>:T):T; &#125;</span><br><span class="line"><span class="keyword">var</span> <span class="attr">getData</span>:<span class="title class_">ConfigFn</span> = <span class="keyword">function</span>&lt;T&gt;(<span class="attr">value</span>:T):T &#123; <span class="keyword">return</span> value; &#125;</span><br><span class="line">getData&lt;<span class="built_in">string</span>&gt;(<span class="string">&#x27;张三&#x27;</span>);</span><br><span class="line"><span class="comment">// 接口定义二</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">ConfigFn</span>&lt;T&gt; &#123; (<span class="attr">value</span>:T):T; &#125;</span><br><span class="line"><span class="keyword">function</span> getData&lt;T&gt;(<span class="attr">value</span>:T):T &#123; <span class="keyword">return</span> value; &#125;</span><br><span class="line"><span class="keyword">var</span> <span class="attr">myGetData</span>:<span class="title class_">ConfigFn</span>&lt;<span class="built_in">string</span>&gt; = getData;</span><br><span class="line"><span class="title function_">myGetData</span>(<span class="string">&#x27;20&#x27;</span>);      <span class="comment">// 20 则报错</span></span><br></pre></td></tr></table></figure>


<h2 id="泛型推导"><a href="#泛型推导" class="headerlink" title="泛型推导"></a>泛型推导</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// TS 在函数调用时会根据变量定义时的类型自动推导</span></span><br><span class="line">type <span class="title class_">Dog</span>&lt;T&gt; = &#123; <span class="attr">name</span>: string, <span class="attr">type</span>: T &#125;</span><br><span class="line"><span class="keyword">function</span> adopt&lt;T&gt;(<span class="attr">dog</span>: <span class="title class_">Dog</span>&lt;T&gt;) &#123; <span class="keyword">return</span> dog &#125;;</span><br><span class="line"><span class="keyword">const</span> dog = &#123; <span class="attr">name</span>: <span class="string">&#x27;ww&#x27;</span>, <span class="attr">type</span>: <span class="string">&#x27;hsq&#x27;</span> &#125;;</span><br><span class="line"><span class="title function_">adopt</span>(dog);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 若不使用函数泛型推导，定义变量时必须指定类型</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">dog</span>: <span class="title class_">Dog</span>&lt;string&gt; = &#123; <span class="attr">name</span>: <span class="string">&#x27;ww&#x27;</span>, <span class="attr">type</span>: <span class="string">&#x27;hsq&#x27;</span> &#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 不想指定则可以使用泛型默认值</span></span><br><span class="line">type <span class="title class_">Dog</span>&lt;T=any&gt; = &#123; <span class="attr">name</span>: string, <span class="attr">type</span>: T &#125;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">dog</span>: <span class="title class_">Dog</span> = &#123; <span class="attr">name</span>: <span class="string">&#x27;ww&#x27;</span>, <span class="attr">type</span>: <span class="string">&#x27;hsq&#x27;</span> &#125;</span><br><span class="line">dog.<span class="property">type</span> = <span class="number">123</span>;    <span class="comment">// type 类型为 any，无法推导</span></span><br></pre></td></tr></table></figure>


<h2 id="泛型约束"><a href="#泛型约束" class="headerlink" title="泛型约束"></a>泛型约束</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 通过 extends 关键字实现类似函数校验参数的功能</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123; <span class="attr">name</span>: <span class="built_in">string</span>; &#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getName</span>(<span class="params">user</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!(user <span class="keyword">instanceof</span> <span class="title class_">Person</span>)) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`<span class="subst">$&#123;user&#125;</span> is not instanceof &quot;Person&quot;`</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> user.<span class="property">name</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GetName</span>&lt;U <span class="keyword">extends</span> <span class="title class_">Person</span>&gt; = U[<span class="string">&#x27;name&#x27;</span>];</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 1、泛型继承接口：lengthRequire 约束 length 属性必须为数值型</span></span><br><span class="line"><span class="keyword">interface</span> lengthRequire&#123; <span class="attr">length</span>:<span class="built_in">number</span> &#125;</span><br><span class="line"><span class="keyword">function</span> getLen&lt;T <span class="keyword">extends</span> lengthRequire&gt;(<span class="attr">arg</span>:T):T &#123;</span><br><span class="line">    <span class="keyword">return</span> arg.<span class="property">length</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、使用类型参数：改写 getProperty</span></span><br><span class="line"><span class="keyword">function</span> getProperty&lt;T, K <span class="keyword">extends</span> keyof T&gt;(<span class="attr">obj</span>: T, <span class="attr">key</span>: K) &#123;</span><br><span class="line">    <span class="keyword">return</span> obj[key]</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> x = &#123; <span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: <span class="number">2</span>, <span class="attr">c</span>: <span class="number">3</span>, <span class="attr">d</span>: <span class="number">4</span> &#125;;</span><br><span class="line"><span class="title function_">getProperty</span>(x, <span class="string">&quot;a&quot;</span>);   <span class="comment">// 正常</span></span><br><span class="line"><span class="title function_">getProperty</span>(x, <span class="string">&quot;m&quot;</span>);   <span class="comment">// 异常</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、使用类类型</span></span><br><span class="line"><span class="keyword">function</span> create&lt;T&gt; (<span class="attr">c</span>: &#123;<span class="title function_">new</span>(): T;&#125;): T &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title function_">c</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 4、泛型条件和推断</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> 条件类型：泛型名A extends 类型B ? 类型C: 类型D</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> 推断 infer：预定义整体结构后，运行时就会自动判断</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> &#123;<span class="type">t: infer Test</span>&#125;：可看作一个包含 t 属性的类型定义</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Foo</span>&lt;T&gt; = T <span class="keyword">extends</span> &#123;<span class="attr">t</span>: infer <span class="title class_">Test</span>&#125; ? <span class="title class_">Test</span>: <span class="built_in">string</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">One</span> = <span class="title class_">Foo</span>&lt;<span class="built_in">number</span>&gt;                       <span class="comment">// string </span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Two</span> = <span class="title class_">Foo</span>&lt;&#123;<span class="attr">t</span>: <span class="built_in">boolean</span>&#125;&gt;                 <span class="comment">// boolean</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Three</span> = <span class="title class_">Foo</span>&lt;&#123;<span class="attr">a</span>: <span class="built_in">number</span>, <span class="attr">t</span>: <span class="function">()=&gt;</span><span class="built_in">void</span>&#125;&gt;   <span class="comment">// ()=&gt;void</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">ReturnType</span>&lt;T&gt; = T <span class="keyword">extends</span> (<span class="function">(<span class="params">...args: <span class="built_in">any</span></span>) =&gt;</span> infer R) ? R : <span class="built_in">never</span>;</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GetSum</span> = <span class="function">(<span class="params">a: <span class="built_in">number</span>, b: <span class="built_in">number</span></span>) =&gt;</span> <span class="built_in">number</span>;</span><br><span class="line"><span class="keyword">type</span> A = <span class="title class_">ReturnType</span>&lt;<span class="title class_">GetSum</span>&gt;          <span class="comment">// number;</span></span><br></pre></td></tr></table></figure>


<h2 id="泛型工具"><a href="#泛型工具" class="headerlink" title="泛型工具"></a>泛型工具</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Partical&lt;T&gt;：将泛型中全部属性变为可选的</span></span><br><span class="line">type <span class="title class_">Partial</span>&lt;T&gt; = &#123; [P <span class="keyword">in</span> keyof T]?: T[P] &#125;  <span class="comment">// 源码</span></span><br><span class="line">type <span class="title class_">Animal</span> = &#123;</span><br><span class="line">    <span class="attr">name</span>: string,</span><br><span class="line">    <span class="attr">age</span>: number,</span><br><span class="line">    <span class="attr">eat</span>: <span class="function">() =&gt;</span> number</span><br><span class="line">&#125;</span><br><span class="line">type <span class="title class_">PartOfAnimal</span> = <span class="title class_">Partial</span>&lt;<span class="title class_">Animal</span>&gt;;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">ww</span>: <span class="title class_">PartOfAnimal</span> = &#123; <span class="attr">name</span>: <span class="string">&#x27;ww&#x27;</span> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Record&lt;K, T&gt;：将 K 所有属性值转为 T 类型，常用来申明一个普通对象</span></span><br><span class="line">type <span class="title class_">Record</span>&lt;K <span class="keyword">extends</span> keyof any,T&gt; = &#123; [key <span class="keyword">in</span> K]: T &#125;   <span class="comment">// 源码</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">obj</span>: <span class="title class_">Record</span>&lt;string, string&gt; = &#123; <span class="string">&#x27;name&#x27;</span>: <span class="string">&#x27;bg&#x27;</span>, <span class="string">&#x27;tag&#x27;</span>: <span class="string">&#x27;武德&#x27;</span> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Pick&lt;T, K&gt;：将 T 类型中的 K 键列表提取出来，生成新的子键值对类型</span></span><br><span class="line">type <span class="title class_">Pick</span>&lt;T, K <span class="keyword">extends</span> keyof T&gt; = &#123; [P <span class="keyword">in</span> K]: T[P] &#125;     <span class="comment">// 源码</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">bird</span>: <span class="title class_">Pick</span>&lt;<span class="title class_">Animal</span>, <span class="string">&quot;name&quot;</span> | <span class="string">&quot;age&quot;</span>&gt; = &#123; <span class="attr">name</span>: <span class="string">&#x27;bird&#x27;</span>, <span class="attr">age</span>: <span class="number">1</span> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Exclude&lt;T, U&gt;：T 类型中去除 T 类型和 U 类型的交集，返回剩余的部分</span></span><br><span class="line">type <span class="title class_">Exclude</span>&lt;T, U&gt; = T <span class="keyword">extends</span> U ? never : T       <span class="comment">// 源码</span></span><br><span class="line">type <span class="variable constant_">T1</span> = <span class="title class_">Exclude</span>&lt;<span class="string">&quot;a&quot;</span> | <span class="string">&quot;b&quot;</span> | <span class="string">&quot;c&quot;</span>, <span class="string">&quot;a&quot;</span> | <span class="string">&quot;b&quot;</span>&gt;;     <span class="comment">// &#x27;c&#x27;</span></span><br><span class="line">type <span class="variable constant_">T2</span> = <span class="title class_">Exclude</span>&lt;string | (<span class="function">()=&gt;</span><span class="keyword">void</span>), <span class="title class_">Function</span>&gt;;  <span class="comment">// string</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Omit&lt;T, K&gt;：去除类型 T 包含 K 的键值对，适用于键值对对象的 Exclude</span></span><br><span class="line">type <span class="title class_">Omit</span> = <span class="title class_">Pick</span>&lt;T, <span class="title class_">Exclude</span>&lt;keyof T, K&gt;&gt;         <span class="comment">// 源码</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">OmitAnimal</span>:<span class="title class_">Omit</span>&lt;<span class="title class_">Animal</span>, <span class="string">&#x27;name&#x27;</span>|<span class="string">&#x27;age&#x27;</span>&gt; = &#123; </span><br><span class="line">  <span class="attr">category</span>: <span class="string">&#x27;lion&#x27;</span>, </span><br><span class="line">  <span class="attr">eat</span>: <span class="function">() =&gt;</span> &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;eat&#x27;</span>) &#125;  <span class="comment">// Omit、Pick 获取非结果、结果</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ReturnType&lt;T&gt;：获取 T 类型(函数)对应的返回值类型，简化源码如下</span></span><br><span class="line">type <span class="title class_">ReturnType</span>&lt;T <span class="keyword">extends</span> func&gt; = T <span class="keyword">extends</span> () =&gt; infer R ? <span class="attr">R</span>: any;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params">x: string | number</span>): string | number &#123;  &#125;</span><br><span class="line">type <span class="title class_">FooType</span> = <span class="title class_">ReturnType</span>&lt;foo&gt;;   <span class="comment">// string | number</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Required&lt;T&gt;：将类型 T 中所有的属性变为必选项</span></span><br><span class="line">type <span class="title class_">Required</span>&lt;T&gt; = &#123; [P <span class="keyword">in</span> keyof T]-?: T[P] &#125;  <span class="comment">// 源码：-? 减去可选属性</span></span><br></pre></td></tr></table></figure>


<h1 id="六、枚举"><a href="#六、枚举" class="headerlink" title="六、枚举"></a>六、枚举</h1><blockquote>
<p>声明一组带名字的常量，用于取值被限定范围内的场景，比如一周有七天、颜色有红绿蓝等。</p>
</blockquote>
<h2 id="根据枚举成员分类"><a href="#根据枚举成员分类" class="headerlink" title="根据枚举成员分类"></a>根据枚举成员分类</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、数字枚举：编译后会生成反向映射表即键值对集合</span></span><br><span class="line"><span class="comment">// 不带初始化器：枚举成员默认从 0 开始并依次递增</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Days</span> &#123; <span class="title class_">Sun</span>, <span class="title class_">Mon</span>, <span class="title class_">Tue</span>, <span class="title class_">Wed</span>, <span class="title class_">Thu</span>, <span class="title class_">Fri</span>, <span class="title class_">Sat</span> &#125;;</span><br><span class="line"><span class="keyword">let</span> <span class="attr">d</span>: <span class="built_in">string</span> = <span class="title class_">Days</span>[<span class="number">0</span>];     <span class="comment">// Sun</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">i</span>: <span class="built_in">number</span> = <span class="title class_">Days</span>.<span class="property">Sat</span>;    <span class="comment">// 6</span></span><br><span class="line"><span class="comment">// 编译结果</span></span><br><span class="line">&#123; </span><br><span class="line">  <span class="number">0</span>: <span class="string">&quot;Sun&quot;</span>, <span class="number">1</span>: <span class="string">&quot;Mon&quot;</span>, <span class="number">2</span>: <span class="string">&quot;Tue&quot;</span>, <span class="number">3</span>: <span class="string">&quot;Wed&quot;</span>, <span class="number">4</span>: <span class="string">&quot;Thu&quot;</span>,</span><br><span class="line">  <span class="number">5</span>: <span class="string">&quot;Fri&quot;</span>, <span class="number">6</span>: <span class="string">&quot;Sat&quot;</span>, <span class="title class_">Fri</span>: <span class="number">5</span>, <span class="title class_">Mon</span>: <span class="number">1</span>, <span class="title class_">Sat</span>: <span class="number">6</span>, <span class="title class_">Sun</span>: <span class="number">0</span>,</span><br><span class="line">  <span class="title class_">Thu</span>: <span class="number">4</span>, <span class="title class_">Tue</span>: <span class="number">2</span>, <span class="title class_">Wed</span>: <span class="number">3</span> </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用初始化器：后面的枚举成员从常数初始值依次递增，</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Days</span> &#123; <span class="title class_">Sun</span>=<span class="number">7</span>, <span class="title class_">Mon</span>, <span class="title class_">Tue</span>, <span class="title class_">Wed</span>=<span class="number">1</span>, <span class="title class_">Thu</span>, <span class="title class_">Fri</span>, <span class="title class_">Sat</span> &#125;;</span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Days</span>_1 &#123; one = <span class="number">2</span>, two &#125;</span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Days</span>_2 &#123; one = <span class="number">10</span> * <span class="title class_">Days</span>_1.<span class="property">one</span> &#125;</span><br><span class="line"><span class="comment">// Days 编译结果</span></span><br><span class="line">&#123; </span><br><span class="line">  <span class="number">1</span>: <span class="string">&quot;Wed&quot;</span>, <span class="number">2</span>: <span class="string">&quot;Thu&quot;</span>, <span class="number">3</span>: <span class="string">&quot;Fri&quot;</span>, <span class="number">4</span>: <span class="string">&quot;Sat&quot;</span>, <span class="number">7</span>: <span class="string">&quot;Sun&quot;</span>, </span><br><span class="line">  <span class="number">8</span>: <span class="string">&quot;Mon&quot;</span>, <span class="number">9</span>: <span class="string">&quot;Tue&quot;</span>, <span class="title class_">Sun</span>: <span class="number">7</span>, <span class="title class_">Mon</span>: <span class="number">8</span>, <span class="title class_">Tue</span>: <span class="number">9</span>, <span class="title class_">Wed</span>: <span class="number">1</span>, </span><br><span class="line">  <span class="title class_">Thu</span>: <span class="number">2</span>, <span class="title class_">Fri</span>: <span class="number">3</span>, <span class="title class_">Sat</span>: <span class="number">4</span>, <span class="title class_">Sun</span>: <span class="number">7</span>, <span class="title class_">Mon</span>: <span class="number">8</span>, <span class="title class_">Tue</span>: <span class="number">9</span> </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、字符串枚举：通过字面量或枚举成员初始化，注意它不会生成反向映射表。</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">StrEnum1</span> &#123; one = <span class="string">&#x27;one&#x27;</span> &#125;               <span class="comment">// 字面量：带引号。</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">StrEnum2</span> &#123; one = <span class="title class_">StrEnum1</span>.<span class="property">one</span> &#125;        <span class="comment">// 定义的枚举成员。</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">StrEnum3</span> &#123; a = <span class="string">&#x27;f&#x27;</span>, b = <span class="title class_">StrEnum1</span>.<span class="property">one</span> &#125; <span class="comment">// 报错：不可混写。</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、异构枚举：混合字符串和数字成员，一般不推荐使用。</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">BooleanLike</span> &#123; <span class="title class_">No</span> = <span class="number">0</span>, <span class="title class_">Yes</span> = <span class="string">&quot;YES&quot;</span> &#125;</span><br></pre></td></tr></table></figure>


<h2 id="根据声明方式分类"><a href="#根据声明方式分类" class="headerlink" title="根据声明方式分类"></a>根据声明方式分类</h2>  <figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 普通枚举：关键词 枚举名，会生成反向映射表。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 常量枚举：const 关键词 枚举名，通过成员访问但不生成反向映射表。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 外部枚举：declear 关键词 枚举名，为防止冲突而不生成反向映射表。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 外部常量枚举：declear const 关键词 枚举名，同常量枚举但提示冲突。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">NumEnum</span> &#123; a, b c &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">enum</span> <span class="title class_">Color</span> &#123; <span class="title class_">Red</span>, <span class="title class_">Green</span>, <span class="title class_">Blue</span> &#125;</span><br><span class="line"><span class="title class_">Color</span>[<span class="string">&#x27;0&#x27;</span>]       <span class="comment">// 报错</span></span><br><span class="line"><span class="title class_">Color</span>.<span class="property">Green</span>      <span class="comment">// 1</span></span><br><span class="line"></span><br><span class="line">declear <span class="keyword">enum</span> <span class="title class_">Animal</span> &#123; cat, dog, tiger &#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Animal</span>)       <span class="comment">// 报错</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Animal</span>.<span class="property">cat</span>)   <span class="comment">// 报错</span></span><br><span class="line"></span><br><span class="line">declear <span class="keyword">const</span> <span class="keyword">enum</span> <span class="title class_">Animal2</span> &#123; cat=<span class="number">1</span>, dog, tiger &#125;</span><br><span class="line"><span class="title class_">Animal2</span>.<span class="property">tiger</span>      <span class="comment">// 3</span></span><br></pre></td></tr></table></figure>





    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2019/11/03/11-1-typescript%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" title="TypeScript 入门">https://chuangges.gitee.io/2019/11/03/11-1-typescript 数据类型/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/08/29/10-2-React%E5%B7%A5%E5%85%B7%E5%BA%93/" rel="prev" title="React 工具库">
      <i class="fa fa-chevron-left"></i> React 工具库
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/11/06/11-2-typescript%20%E8%BF%9B%E9%98%B6%E8%AF%AD%E6%B3%95/" rel="next" title="TypeScript 进阶语法">
      TypeScript 进阶语法 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E7%AE%80%E4%BB%8B"><span class="nav-number">1.</span> <span class="nav-text">一、简介</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%80%E5%8F%91%E5%87%86%E5%A4%87"><span class="nav-number">1.1.</span> <span class="nav-text">开发准备</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B"><span class="nav-number">1.2.</span> <span class="nav-text">基础类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F"><span class="nav-number">1.3.</span> <span class="nav-text">类型变量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="nav-number">1.4.</span> <span class="nav-text">操作符</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="nav-number">1.5.</span> <span class="nav-text">运算符</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81%E6%8E%A5%E5%8F%A3"><span class="nav-number">2.</span> <span class="nav-text">二、接口</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B1%9E%E6%80%A7%E7%B1%BB%E5%9E%8B"><span class="nav-number">2.1.</span> <span class="nav-text">属性类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E7%B1%BB%E5%9E%8B"><span class="nav-number">2.2.</span> <span class="nav-text">函数类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%AF%E7%B4%A2%E5%BC%95%E7%B1%BB%E5%9E%8B"><span class="nav-number">2.3.</span> <span class="nav-text">可索引类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E7%B1%BB%E5%9E%8B"><span class="nav-number">2.4.</span> <span class="nav-text">类类型</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E7%B1%BB"><span class="nav-number">3.</span> <span class="nav-text">三、类</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF"><span class="nav-number">3.1.</span> <span class="nav-text">继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%9A%E7%BB%A7%E6%89%BF"><span class="nav-number">3.2.</span> <span class="nav-text">多继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BF%AE%E9%A5%B0%E7%AC%A6"><span class="nav-number">3.3.</span> <span class="nav-text">修饰符</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AD%98%E5%8F%96%E5%99%A8"><span class="nav-number">3.4.</span> <span class="nav-text">存取器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8A%BD%E8%B1%A1%E7%B1%BB"><span class="nav-number">3.5.</span> <span class="nav-text">抽象类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%AB%98%E7%BA%A7%E6%8A%80%E5%B7%A7"><span class="nav-number">3.6.</span> <span class="nav-text">高级技巧</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81%E5%87%BD%E6%95%B0"><span class="nav-number">4.</span> <span class="nav-text">四、函数</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%9A%E4%B9%89"><span class="nav-number">4.1.</span> <span class="nav-text">定义</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%86%E7%B1%BB"><span class="nav-number">4.2.</span> <span class="nav-text">分类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%82%E6%95%B0"><span class="nav-number">4.3.</span> <span class="nav-text">参数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%87%8D%E8%BD%BD"><span class="nav-number">4.4.</span> <span class="nav-text">重载</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94%E3%80%81%E6%B3%9B%E5%9E%8B"><span class="nav-number">5.</span> <span class="nav-text">五、泛型</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8"><span class="nav-number">5.1.</span> <span class="nav-text">基础使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B3%9B%E5%9E%8B%E6%8E%A8%E5%AF%BC"><span class="nav-number">5.2.</span> <span class="nav-text">泛型推导</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B3%9B%E5%9E%8B%E7%BA%A6%E6%9D%9F"><span class="nav-number">5.3.</span> <span class="nav-text">泛型约束</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B3%9B%E5%9E%8B%E5%B7%A5%E5%85%B7"><span class="nav-number">5.4.</span> <span class="nav-text">泛型工具</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%AD%E3%80%81%E6%9E%9A%E4%B8%BE"><span class="nav-number">6.</span> <span class="nav-text">六、枚举</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%B9%E6%8D%AE%E6%9E%9A%E4%B8%BE%E6%88%90%E5%91%98%E5%88%86%E7%B1%BB"><span class="nav-number">6.1.</span> <span class="nav-text">根据枚举成员分类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%B9%E6%8D%AE%E5%A3%B0%E6%98%8E%E6%96%B9%E5%BC%8F%E5%88%86%E7%B1%BB"><span class="nav-number">6.2.</span> <span class="nav-text">根据声明方式分类</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
